<?php
/**
* Scans images on the server location and creates an album for those images.
*/
class scanner
{
	public $album_id=0;
	
	private $album_folder='/tmp';
	private $album_name='';
	
	private $error='';
	private $BR="\r\n<br />";
	private $subdomain_id=0;
	
	private $images_scanned_counter = 0;
	
	private $db;
	
	public function __construct($album_folder='/tmp')
	{
		$this->db = new mysql();
		
		# @see images-preview.php
		# Allow blank calls to this call that won't register the album
		if($album_folder=='/tmp') return;
		
		global $subdomain_id;
		$this->subdomain_id = (int)$subdomain_id;
		
		$album_folder = $this->valid_name($album_folder);
		if(!is_dir($album_folder))
		{
			die('Not an album folder: '.$album_folder);
		}
		else
		{
			$this->album_folder = $album_folder;
			chdir($album_folder);
		}
		
		# Avlid not alphanets and multiple white spaces
		$this->album_name = basename($album_folder);
		$this->album_name = preg_replace('/[\d\-\_]{6,}/', '', $this->album_name);
		$this->album_name = implode(' ', array_filter(array_map('trim', preg_split('/[^0-9a-z\-]/is', $this->album_name))));
		#echo 'Album: '.$this->album_name;
		
		$this->album_id = $this->register_album();
		$this->register_images();
	}
	
	/**
	* Save the album and return its ID
	*/
	private function register_album()
	{
		$album = array('album_id' => 0);
		$is_approved = (defined('AUTOAPPROVED_ALBUMS') && in_array(constant('AUTOAPPROVED_ALBUMS'), array('true', 'TRUE', 'yes', 'YES', 'Y')))?'Y':'N';
		
		# Try to read out the album folder description in the corresponding readme.txt file.
		$album_description = '';
		if(is_file("{$this->album_folder}/readme.txt"))
		{
			$album_description = addslashes(nl2br(file_get_contents("{$this->album_folder}/readme.txt")));
		}
		
		$register_album_sql="
INSERT IGNORE INTO gallery_albums (
	subdomain_id, added_on, is_active, is_approved,
	album_name, album_folder,
	album_name_original, album_folder_original,
	album_description
) VALUES (
	{$this->subdomain_id}, UNIX_TIMESTAMP(CURRENT_TIMESTAMP()), 'Y', '{$is_approved}',
	'{$this->album_name}', '{$this->album_folder}',
	'{$this->album_name}', '{$this->album_folder}',
	'{$album_description}'
);";
		#die($register_album_sql);
		if($this->db->query($register_album_sql))
		{
			$find_album_sql="SELECT album_id FROM gallery_albums WHERE album_folder='{$this->album_folder}';";
			$album = $this->db->row($find_album_sql);
			if(!isset($album['album_id'])) $album = array('album_id' => 0);
		}
		return $album['album_id'];
	}
	
	/**
	* Save all album images into the database
	*/
	private function register_images()
	{
		#chdir($this->album_folder);
		$images = array_merge(
			glob('*.jpg', GLOB_NOSORT),
			glob('*.JPG', GLOB_NOSORT) # Bad, some camera save in upper case
		);
		if(!count($images))
		{
			$this->error = 'Cannot find images. Check extension, case sensitivity, ...';
		}
		
		#print_r($images); #die();
		foreach($images as $i => $image)
		{
			$this->register_image($image);
		}
		
		# Update images counter
		#$counter = count($images);
		#$update_sql="UPDATE gallery_images SET images_counter=images_counter+{$counter} WHERE album_id={$this->album_id};";
	}
	
	/**
	* Register an individual image into the database
	*/
	private function register_image($image_file='default.jpg')
	{
		$category_id = DEFAULT_CATEGORY_ID; # 0; # Unknown by default
		#chdir($this->album_folder);
		
		# INSERT INTO ...
		# save other info, exif, dimensions, colors, sizes, ...
		# create thumbs (resize), small pic, medium pic, large pic
		# move original pic to its own folder - for original file download purpose
		#$image_id = mt_rand(1000, 9999);
		
		$image_file = addslashes($this->valid_name($image_file));
		
		$full_path = "{$this->album_folder}/{$image_file}";
		#die($full_path);
		if(!is_file($full_path)) return null;
		
		$filesize_bytes = filesize($full_path);
		$image_code = tools::unique_code();
		$image_hash = sha1_file($full_path);
		
		$info = array();
		$image_sizes = getimagesize($full_path, $info);
		$dimension_width = isset($image_sizes[0])?$image_sizes[0]:0;
		$dimension_height = isset($image_sizes[1])?$image_sizes[1]:0;
		
		$created_on = filemtime($full_path);
		if(!$created_on) $created_on=0;
		
		$image_caption = addslashes(
			implode(' ',
				preg_split('/[^a-z0-9]+/is', preg_replace('/\.(jpg|jpeg|gif|png)$/is', '', $image_file))
			)
		);
		
		$is_approved = (defined('AUTOAPPROVED_IMAGES') && in_array(constant('AUTOAPPROVED_IMAGES'), array('true', 'TRUE', 'yes', 'YES', 'Y')))?'Y':'N';
		$insert_image_sql="
INSERT INTO gallery_images (
	subdomain_id, added_on, is_active, is_approved,
	created_on,
	dimension_width, dimension_height, filesize_bytes,
	image_code,
	image_name, image_caption, image_keywords, image_hash,
	image_description
) VALUES (
	{$this->subdomain_id}, UNIX_TIMESTAMP(CURRENT_TIMESTAMP()), 'Y', '{$is_approved}',
	{$created_on},
	{$dimension_width}, {$dimension_height}, {$filesize_bytes},
	'{$image_code}',
	'{$image_file}', '{$image_caption}', '', '{$image_hash}',
	''
);";
		#die($insert_image_sql);
		$this->db->query($insert_image_sql);
		if($image_id = $this->db->insert_id())
		{
			# Add image sizes
			# Add as default image size for later modifications
			$size_id = THUMBNAIL_ORIGINAL_SIZE_ID;
			$image_mime = exif_imagetype($full_path);
			$image_exifinfo = ''; # addslashes(serialize(exif_read_data($full_path)));
			#print_r(exif_read_data($full_path)); die();

			$automatic_scanned_size_sql="
INSERT INTO gallery_images_sizes (
	subdomain_id, added_on, is_active,
	image_id, size_id, image_filesize,
	image_name, image_name_local, image_hash,
	image_mime, image_exifinfo
) VALUES (
	{$this->subdomain_id}, UNIX_TIMESTAMP(CURRENT_TIMESTAMP()), 'Y',
	{$image_id}, {$size_id}, {$filesize_bytes},
	# NOT full_path here
	'{$image_file}', '', '{$image_hash}',
	'{$image_mime}', '{$image_exifinfo}'
);";
			#die($automatic_scanned_size_sql);
			$this->db->query($automatic_scanned_size_sql);
			
			
			# Also, assign the image to the album
			$album_assign_sql="INSERT INTO gallery_images_albums (subdomain_id, added_on, is_active, is_approved, image_id, album_id) VALUES ({$this->subdomain_id}, UNIX_TIMESTAMP(CURRENT_TIMESTAMP()), 'Y', 'Y', {$image_id}, {$this->album_id});";
			$this->db->query($album_assign_sql);
			
			# Mark as unknown category
			$album_assign_sql="INSERT INTO gallery_images_categories (subdomain_id, added_on, is_active, is_approved, image_id, category_id) VALUES ({$this->subdomain_id}, UNIX_TIMESTAMP(CURRENT_TIMESTAMP()), 'Y', 'Y', {$image_id}, {$category_id});";
			$this->db->query($album_assign_sql);
			
			++$this->images_scanned_counter;
		}

		#echo "{$this->BR}Registering: {$image_file} - Image ID: {$image_id}, Album ID: {$this->album_id}, Category ID: {$category_id}";

		return $image_id;
	}
	
	
	
	/**
	* Pre-views an image file
	*/
	public function preview($image_id=0, $protection_code='')
	{
		$image_id = (int)$image_id;
		$protection_code = tools::sanitize($protection_code);
		
		# @todo Add thumbnail size in the request parameter
		$size_id = THUMBNAIL_ORIGINAL_SIZE_ID;
		$preview_image_sql="SELECT image_name FROM gallery_images_sizes WHERE image_id={$image_id} AND size_id={$size_id} LIMIT 1;";
		$preview = $this->db->row($preview_image_sql);
		if(isset($preview['image_name']))
		{
			if(file_exists($preview['image_name']))
			{
				if(headers_sent()) die('Error: Headers sent already. Not showing the image.');
				
				$logomark = new logomark(__BASE__.'/'.LOGOMARK_IMAGE_FULLPATH);
				
				#$logomark->show_image($preview['image_name']); # works
				#header('Content-Type: image/jpeg'); readfile($preview['image_name']); # works
				
				# Resizing is for test purpose only.
				# Rather resize the original image itself.
				#$logomark->resize_to(800, 600);
				#$logomark->resize_to(300, 400);	
				
				$logomark->show_image($preview['image_name']); # works
			}
			else
			{
				echo 'File not found - ', $preview['image_name'];
			}
		}
		else
		{
			echo 'Invalid request - file/size information not stored properly.';
		}
	}
	
	
	/**
	* Serve requested size from the cache or create the cache
	*/
	public function preview_size($image_id=0, $protection_code='', $size_text='')
	{
		$image_id = (int)$image_id;
		$protection_code = tools::sanitize($protection_code);

		$size = new sizes();
		$size_text = tools::sanitize($size_text);
		if(!$size_id = $size->size_id($size_text))
		{
			die('Size does not exist.');
		}
		
		# image > album > thumbnails location
		$image_to_album_thumbnail_location_sql="
SELECT
	i.image_id,
	ia.album_id,
	`as`.size_id,
	`as`.store_location
FROM gallery_albums_sizes `as`
INNER JOIN gallery_images_albums ia ON ia.album_id=as.album_id
INNER JOIN gallery_images i ON i.image_id = ia.image_id
WHERE
	ia.image_id={$image_id}
	AND `as`.size_id={$size_id}
;";
		#die($image_to_album_thumbnail_location_sql);
		$size_details=$this->db->row($image_to_album_thumbnail_location_sql);
		if(!isset($size_details['store_location']))
			die("Missing thumbs store location for the album of this image #{$image_id}, size: #{$size_id}. Album not determined.");
		if(!is_dir($size_details['store_location']))
		{
			# Try to create that path, as it may be a first time request.
			if(!mkdir($size_details['store_location'], 0777, true)) die('Can not create the thumbnails directory for the first time.');
		}
		if(!is_writable($size_details['store_location']))
			die("Store location not writable - {$size_details['store_location']}");
		
		#print_r($size_details); #die();
		# [location]/album_id/image_id/size_id.jpg
		$thumb_path = "{$size_details['store_location']}/{$size_details['album_id']}/{$size_details['image_id']}/{$size_details['size_id']}.jpg";
		#die($thumb_path);
		if(is_file($thumb_path))
		{
			# already cached
			header('Content-Type: image/jpeg'); readfile($thumb_path); return;
		}
/*
Array
(
    [image_id] => 250
    [album_id] => 1
    [size_id] => 4
    [store_location] => D:\thumbs\custom-relocated\meds
)*/

		# Proceed to create the thumnbail of this size
		
		# Find out the orignal image path
		$original_size_id = THUMBNAIL_ORIGINAL_SIZE_ID;
		$original_image_sql="SELECT image_name FROM gallery_images_sizes WHERE image_id={$image_id} AND size_id={$original_size_id} LIMIT 1;";
		$original = $this->db->row($original_image_sql);
		#print_r($original); die($original_image_sql);
		if(isset($original['image_name']))
		{
			if(file_exists($original['image_name']))
			{
				if(headers_sent()) die('Error: Headers sent already. Not showing the image.');
				
				$logomark = new logomark(__BASE__.'/'.LOGOMARK_IMAGE_FULLPATH);
				
				# Find out the size details
				$sizes_sql="SELECT dimension_width width, dimension_height height FROM gallery_sizes WHERE size_id={$size_id};";
				$size = $this->db->row($sizes_sql);
				#print_r($size); die($sizes_sql);
				$logomark->resize_to($size['width'], $size['height']);
				
				$dir = dirname($thumb_path); if(!is_dir($dir)) mkdir($dir, 0777, true); # @todo It may fail
				#die($thumb_path);
				$logomark->save_to($thumb_path);
				
				$logomark->show_image($original['image_name']); # works
			}
			else
			{
				echo 'File not found - ', $original['image_name'];
			}
		}
		else
		{
			echo 'Invalid request - file/size information not stored properly.';
		}
	}
	
	
	/**
	* Pre-views an image file
	*/
	public function preview_thumbnail($image_id=0, $protection_code='')
	{
		$image_id = (int)$image_id;
		$protection_code = tools::sanitize($protection_code);
		
		$original_size_id = THUMBNAIL_ORIGINAL_SIZE_ID;
		$original_image_sql="SELECT image_name FROM gallery_images_sizes WHERE image_id={$image_id} AND size_id={$original_size_id} LIMIT 1;";
		#echo ($original_image_sql);
		$original = $this->db->row($original_image_sql);
		if(!isset($original['image_name']))
			die('Original image file not found.');
		
		# @todo Add thumbnail size in the request parameter
		$thumbnail_size_id = THUMBNAIL_HOMEPAGE_SIZE_ID;
		
		$size = $this->db->row("SELECT * FROM gallery_sizes WHERE size_id={$thumbnail_size_id};");
		#print_r($size);
		
		$preview_thumbnail_image_sql="SELECT image_name FROM gallery_images_sizes WHERE image_id={$image_id} AND size_id={$thumbnail_size_id} LIMIT 1;";
		#die($preview_thumbnail_image_sql);
		$preview = $this->db->row($preview_thumbnail_image_sql);
		if(isset($preview['image_name']) && $preview['image_name'])
		{
			if(file_exists($preview['image_name']))
			{
				if(headers_sent()) die('Headers sent already. Not showing the image.');
				
				header('Content-Type: image/jpeg');
				readfile($preview['image_name']);
			}
			else
			{
				if($thumb_file = $this->create_thumbnail($image_id, $thumbnail_size_id, $size, $original))
				{
					header('Content-Type: image/jpeg');
					readfile($thumb_file);
				}
				else
				{
					echo 'File not found - ', $preview['image_name'];
				}
			}
		}
		else
		{
			# Create a thumbnail
			$thumb_file = $this->create_thumbnail($image_id, $thumbnail_size_id, $size, $original);
			
			header('Content-Type: image/jpeg');
			readfile($thumb_file);
		}
	}
	
	private function create_thumbnail($image_id=0, $thumbnail_size_id=0, $size=array(), $original=array())
	{
		$image_id = (int)$image_id;
		$thumbnail_size_id = (int)$thumbnail_size_id;
		
		$find_album="SELECT album_id FROM gallery_images_albums WHERE image_id={$image_id};";
		$album = $this->db->row($find_album);
		if(!isset($album['album_id'])) $album = array('album_id' => 0);
		$thumb_file = __BASE__."/images/{$album['album_id']}/{$image_id}/{$thumbnail_size_id}.jpg";
		if(!is_dir(dirname($thumb_file))) mkdir(dirname($thumb_file), 0777, true);
		#echo $thumb_file;
		#print_r($album);
		#echo 'Invalid request - file/size information not stored properly.';
		
		# Original thumnailer
		#$thumbnailer = new thumbnailer($original['image_name']);
		#$thumbnailer->generate($new_width=$size['dimension_width'], $new_height=$size['dimension_height'], $thumb_file, $quality=75);
		
		# Rather use cropnail
		$cropnail = new cropnail($size['dimension_width'], $size['dimension_height']);
		$cropnail->resize($original['image_name'], $thumb_file, 0);
		
		$image_filesize = filesize($thumb_file);
		$image_hash = sha1_file($thumb_file);
		#$original['image_name'], $path
		# [dimension_width] => 60
		# [dimension_height] => 45
		
		global $subdomain_id;
		$record_thumbnail_image_sql="
INSERT INTO `gallery_images_sizes`(
	`subdomain_id`,`added_on`,
	`is_active`,`is_approved`,`is_valid`,
	`image_id`,`size_id`,`image_filesize`,
	`image_name`, `image_name_local`, `image_hash`, `image_mime`,
	`image_exifinfo`
) VALUES (
	'{$subdomain_id}', UNIX_TIMESTAMP(CURRENT_TIMESTAMP()),
	'Y', 'Y', 'Y',
	'{$image_id}', '{$thumbnail_size_id}', '{$image_filesize}',
	'{$thumb_file}', '', '{$image_hash}', '',
	''
);";
		$this->db->query($record_thumbnail_image_sql);
		
		return($thumb_file);
	}
	
	
	
	/**
	* Valid name
	*/
	private function valid_name($image_path_name='')
	{
		$image_path_name = str_replace('\\', '/', $image_path_name);
		$image_path_name = preg_replace('/[^a-z0-9\_\-\.\ \/\:]+/is', '', $image_path_name);
		
		return $image_path_name;

	}
	
	/**
	* See how many iages were scanned
	*/
	public function total_images_scanned()
	{
		return $this->images_scanned_counter;
	}
	
	/**
	* Patch counter
	*/
	public function patch_counter()
	{
		$total_images_scanned = (int)$this->total_images_scanned();
		$album_id = (int)$this->album_id;
		$patch_sql="UPDATE gallery_albums SET images_counter={$total_images_scanned} WHERE album_id={$album_id};";
		return $this->db->query($patch_sql);
	}
}
?>